package com.snap.vseries.manager;

import android.os.Environment;
import android.util.Log;
import android.util.SparseArray;

import com.orhanobut.logger.Logger;
import com.snap.vseries.AppConfig;
import com.snap.vseries.bean.ChannelBean;
import com.snap.vseries.bean.ExpInfo;
import com.snap.vseries.bean.HoleInfo;
import com.snap.vseries.bean.LightBean;
import com.snap.vseries.utils.ExcelUtil;
import com.snap.vseries.utils.FileUtils;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;


/**
 * 文件Mgr
 * 总体流程分2个步骤
 * 序列化：   bean --> proto stuff --> Gzip压缩后写入文件
 * 反序列化   文件经Gzip解压后字节流读出  -->  proto stuff  --> bean
 */
public class FileManager {

    private static final String TAG = "FileManager";

    private FileManager() {
    }

    public static FileManager getInstance() {
        return FileManagerHolder.manager;
    }

    public void createExpFile(String expName) {
        File file = new File(getExpFilePath(expName));
        FileUtils.mkFile(file);
    }

    /**
     * 将荧光强度数据导出成excel格式
     */
    public boolean exportExcel(ExpInfo experimentInfo, String path) {
        HoleInfo holeInfo = experimentInfo.getHoleInfo();
        if (holeInfo == null) {
            return false;
        }
        SparseArray<List<LightBean>> data = experimentInfo.getLightData();
        SparseArray<ChannelBean> crossTalked = holeInfo.getChannelData();
        if (crossTalked == null) {
            Logger.e("通道数据为空");
            return false;
        }
        int runCycle = experimentInfo.getRunCycle();
        int holeCount = AppConfig.TOTAL_HOLE_COUNT;
        int channelCount = 4;
        Workbook workbook = new HSSFWorkbook();
        //每个通道存一个sheet
        int[][] dataArray = new int[runCycle][holeCount * channelCount];
        float[][][] channelArray = new float[channelCount][runCycle][holeCount];
        float[][] ctValue = new float[1][4];
        for (int i = 0; i < holeCount * channelCount; i++) {
            ChannelBean ctBean = crossTalked.get(i);
            if (ctBean != null) {
                ctValue[0][i] = ctBean.getCtValue();
            }
            int whichChannel = i / holeCount;
            int whichHole = i % holeCount;

            List<LightBean> holeData = data.get(i);
            if (holeData != null) {
                int size = holeData.size();
                for (int j = 0; j < size; j++) {
                    dataArray[j][i] = holeData.get(j).getIntensity();
                }
            }
            if (crossTalked.get(i) == null) {
                continue;
            }
            float[] cross = crossTalked.get(i).getOrigin();

            if (cross != null) {
                for (int j = 0; j < cross.length; j++) {
                    channelArray[whichChannel][j][whichHole] = cross[j];
                }
            }
        }
        ExcelUtil.createExcelArrayFloat(workbook, "Ct", ctValue);
        for (int i = 0; i < channelCount; i++) {
            ExcelUtil.createExcelArrayFloat(workbook, AppConfig.CHANNEL_NAMES[i], channelArray[i]);
        }
        ExcelUtil.createExcelArray(workbook, "all", dataArray);
        double[] crossParams = experimentInfo.getCrosstalk();
        if (crossParams != null) {
            float[][] outCross = new float[4][4];
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    outCross[i][j] = (float) crossParams[i * 4 + j];
                }
            }
            ExcelUtil.createExcelArrayFloat(workbook, "CrossTalk", outCross);
        }
        File file = new File(path);
        FileUtils.mkFileAndCover(file);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            workbook.write(fos);
            FileUtils.ensureWriteFile(file);
            return true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NullPointerException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    /**
     * 将exp bean存入文件
     */
    public boolean saveExpData(ExpInfo experimentInfo) {
        if (experimentInfo == null) {
            return false;
        }

        byte[] byteArray = FileUtils.serialize(experimentInfo);
        File file = new File(getExpFilePath(experimentInfo.getName()));
        FileUtils.mkFile(file);
        return FileUtils.writeFile(file, byteArray);
    }

    /**
     * 将template bean存入文件
     */
    public boolean saveTempData(ExpInfo templateInfo, String testProject) {
        if (templateInfo == null) {
            return false;
        }
        byte[] byteArray = FileUtils.serialize(templateInfo);
        File file = new File(getTempFilePath(testProject));
        FileUtils.mkFile(file);
        return FileUtils.writeFile(file, byteArray);
    }

    public ExpInfo getExpDataByName(String fileName) {
        String path = getExpFilePath(fileName);
        long t1 = System.currentTimeMillis();
        File file = new File(path);
        if (!file.exists()) return null;
        byte[] byteArray = FileUtils.readFile(file);
        if (byteArray == null) return null;
        ExpInfo exp = FileUtils.deserialize(byteArray, ExpInfo.class);
        Log.e(TAG, "读取花费时间" + (System.currentTimeMillis() - t1));
        exp.fillNecessary();//填充必要的分析参数 分析协议
        return exp;
    }


    public ExpInfo getTempDataByName(String fileName) {
        return getTempData(getTempFilePath(fileName));
    }

    /**
     * 从文件中读取出 template bean
     */
    private ExpInfo getTempData(String path) {
        File file = new File(path);
        if (!file.exists()) {
            return null;
        }
        byte[] byteArray = FileUtils.readFile(file);
        if (byteArray == null) {
            return null;
        }
        return FileUtils.deserialize(byteArray, ExpInfo.class);
    }

    public boolean removeTempData(String path) {
        File file = new File(getTempFilePath(path));
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    public boolean removeExpData(String path) {
        File file = new File(getExpFilePath(path));
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    public boolean removeFile(String path) {
        File file = new File(getExpFilePath(path));
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * 删除目录及目录下的文件
     *
     * @param path 要删除的目录的文件路径
     */
    public boolean deleteDirectory(String path) {
        File fileDirectory = new File(path);
        if (!fileDirectory.exists()) {
            return false;
        }
        if (!path.endsWith(File.separator)) {
            path = path + File.separator;
        }
        File dirFile = new File(path);
        if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
            return false;
        }
        boolean flag = true;
        File[] files = dirFile.listFiles();
        for (File file : files) {
            if (file.isFile()) {
                flag = removeFile(file.getAbsolutePath());
                if (!flag) {
                    break;
                }
            } else if (file.isDirectory()) {
                flag = deleteDirectory(file
                        .getAbsolutePath());
                if (!flag) {
                    break;
                }
            }
        }
        if (!flag) {
            return false;
        }
        return dirFile.delete();
    }

    public String getExpFilePath(String fileName) {
        return Environment.getExternalStorageDirectory().getPath() + AppConfig.EXPERIMENT_DIRECTORY + fileName + ".exp";
    }

    public String getTempFilePath(String demoID) {
        return Environment.getExternalStorageDirectory().getPath() + AppConfig.TEMPLATE_DIRECTORY + demoID + ".tep";
    }

    public String getExcelFilePath(String fileName) {
        return Environment.getExternalStorageDirectory().getPath() + AppConfig.EXCEL_DIRECTORY + fileName + ".xls";
    }

    private static class FileManagerHolder {
        private static final FileManager manager = new FileManager();
    }
}
